/**
 * Unity单例行为基类 (SingletonBehaviour)
 * 
 * 功能说明：
 * - 为Unity MonoBehaviour提供单例模式的基类实现
 * - 确保全局只有一个实例存在
 * - 自动管理实例的创建和销毁
 * - 提供安全的实例访问接口
 * 
 * 设计模式：
 * - 单例模式 (Singleton Pattern)
 * - 懒加载 (Lazy Loading)
 * 
 * 使用方式：
 * 1. 继承SingletonBehaviour<T>创建单例类
 * 2. 通过Instance属性访问实例
 * 3. 重写Awake()和OnDestroy()进行自定义初始化
 * 
 * 注意事项：
 * - 单例对象会在场景切换时保持存在
 * - 重复创建会输出错误日志
 * - 建议在Awake()中进行初始化工作
 */

using UnityEngine;

namespace UnityHelpers
{
    /**
     * Unity单例行为基类
     * 
     * 泛型参数 T: 继承此类的具体类型
     * 要求：T必须是MonoBehaviour的子类
     */
    public class SingletonBehaviour<T> : MonoBehaviour where T : MonoBehaviour
    {
        /**
         * 单例实例
         * 
         * 说明：
         * - 静态字段，确保全局唯一
         * - 私有字段，只能通过Instance属性访问
         * - 在Awake()中初始化，在OnDestroy()中清理
         */
        private static T _instance;

        /**
         * 单例实例访问器
         * 
         * 功能：
         * - 提供对单例实例的安全访问
         * - 只读属性，外部无法修改实例
         * - 如果实例不存在，返回null
         * 
         * 使用示例：
         * var instance = MySingleton.Instance;
         */
        public static T Instance
        {
            get
            {
                return _instance;
            }
        }
        
        /**
         * Unity生命周期：Awake方法
         * 
         * 功能：
         * - 单例模式的初始化逻辑
         * - 检查是否已存在实例，防止重复创建
         * - 设置当前对象为单例实例
         * 
         * 工作流程：
         * 1. 检查_instance是否为空
         * 2. 如果为空，设置当前对象为实例
         * 3. 如果不为空，输出错误日志并销毁当前对象
         * 
         * 注意：
         * - 子类如果需要重写此方法，必须调用base.Awake()
         * - 建议在base.Awake()之后进行自定义初始化
         */
        protected virtual void Awake()
        {
            if (_instance == null)
            {
                // 设置当前对象为单例实例
                _instance = this as T;
            }
            else    
            {
                // 重复创建实例，输出错误日志
                Debug.LogError($"SingletonBehaviour: 单例重复创建错误 - 已存在{typeof(T).Name}实例");
            }
        }

        /**
         * Unity生命周期：OnDestroy方法
         * 
         * 功能：
         * - 单例模式的清理逻辑
         * - 在对象销毁时清理静态实例引用
         * - 防止销毁后仍能访问已销毁的实例
         * 
         * 工作流程：
         * 1. 检查当前对象是否为单例实例
         * 2. 如果是，将_instance设置为null
         * 3. 如果不是，输出错误日志
         * 
         * 注意：
         * - 子类如果需要重写此方法，必须调用base.OnDestroy()
         * - 建议在base.OnDestroy()之前进行自定义清理
         */
        protected virtual void OnDestroy()
        {
            if (_instance == this)
            {
                // 清理单例实例引用
                _instance = null;
            }
            else
            {
                // 非单例实例被销毁，输出错误日志
                Debug.LogError($"SingletonBehaviour: 单例重复销毁错误 - 已存在{typeof(T).Name}实例");
            }
        }
    }
}